package data.complex;

import java.util.ArrayList;
import java.util.List;

import data.base.Bary3;
import data.base.Vector3;
import data.base.Vertex;
import data.hierarchy.IVertexProvider;
import data.hierarchy.TriangleGroup;


public class Triangle implements IVertexProvider{
  private Vertex a;
  private Vertex b;
  private Vertex c;
  private List<Vertex> points;
  private TriangleGroup group;
  
  public Triangle(Vertex a, Vertex b, Vertex c){
    this.a = a;
    this.b = b;
    this.c = c;
  }
  
  public Vector3 getNormal(boolean normalize){    
    return new Vector3(
        new Vector3(a, b), 
        new Vector3(a, c), 
        normalize);
  }
  
  public double getArea(){
    return getNormal(false).getMagnitude() / 2;
  }  
  
  public Bary3 getBarycentricCoordinates(Vector3 p){
    Vector3 normal = getNormal(false);
    
    if(Math.abs(normal.getX()) > Math.abs(normal.getY())){
      if(Math.abs(normal.getX()) > Math.abs(normal.getZ())){
        return getBarycentricCoordinates(Vector3._Y, Vector3._Z, p);
      }
    }
    else{
      if(Math.abs(normal.getY()) > Math.abs(normal.getZ())){
        return getBarycentricCoordinates(Vector3._X, Vector3._Z, p);
      }
    }
    return getBarycentricCoordinates(Vector3._X, Vector3._Y, p);
  }

  private Bary3 getBarycentricCoordinates(int u, int v, Vector3 p){
    double ax = a.get(u) - p.get(u);
    double ay = a.get(v) - p.get(v);
    double bx = b.get(u) - p.get(u);
    double by = b.get(v) - p.get(v);
    double cx = c.get(u) - p.get(u);
    double cy = c.get(v) - p.get(v);
    
    double a = bx*cy - by*cx;
    double b = cx*ay - cy*ax;
    double c = ax*by - ay*bx;
    
    double sum = a+b+c;
    
    return new Bary3(a / sum, b / sum, c / sum);
  }
   
  public double getPerimeter(){
    return a.distanceTo(b) + b.distanceTo(c) + c.distanceTo(a);
  }
  
  public Vertex getA() {
    return a;
  }

  public Vertex getB() {
    return b;
  }

  public Vertex getC() {
    return c;
  }
  
  public void setGroup(TriangleGroup group){
    this.group = group;
  }

  @Override
  public Iterable<Vertex> getVertices() {
    if(points == null){
      points = new ArrayList<Vertex>();
      points.add(a);
      points.add(b);
      points.add(c);
    }      
    return points;
  }

  public TriangleGroup getGroup() {
    return group;
  }
}
